<?php

namespace App\Http\Controllers;

use App\Exceptions\InternalException;
use App\Exceptions\InvalidRequestException;
use App\Models\Order;
use Carbon\Carbon;
use Endroid\QrCode\QrCode;
use Illuminate\Http\Request;
use App\Events\OrderPaid;

class PaymentController extends Controller
{
    //支付宝支付
    public function payByAlipay(Order $order, Request $request)
    {
        //判断订单是否属于当前用户
        $this->authorize('own',$order);

        //订单已支付或已关闭
        if ($order->paid_at || $order->closed){
            throw new InvalidRequestException('订单状态不正确');
        }

        return app('alipay')->web([
            'out_trade_no' => $order->no, //订单编号
            'total_amount' => $order->total_amount,//订单金额,单位元,支持小数点两位
            'subject'      => '支付 laravel shop 订单:'.$order->no, //订单标题
        ]);
    }

    //支付宝前端回调页面
    public function alipayReturn()
    {
        //校验提交的参数是否合法
        //app('alipay')->verify() 用于校验提交的参数是否合法，支付宝的前端跳转会带有数据签名，通过校验数据签名可以判断参数是否被恶意用户篡改。同时该方法还会返回解析后的参数。
        //$data = app('alipay')->verify();
        //dd($data);

        try{
            app('alipay')->verify();
        }catch (\Exception $e){
            return view('pages.error', ['msg' => '数据不正确']);
        }

        return view('pages.success', ['msg' => '付款成功']);
    }

    //支付宝服务器回调
    public function alipayNotify()
    {
        //校验输入参数
        $data = app('alipay')->verify();
        // $data->out_trade_no 拿到订单流水号,并在数据库中查询
        $order = Order::where('no',$data->out_trade_no)->first();
        //正确是 有的,为了代码的健壮性
        if (!$order){
            return 'fail';
        }

        //如果已支付
        if ($order->paid_at){
            //返回数据给支付宝
            return app('alipay')->success();
        }
        $order->update([
            'paid_at'           => Carbon::now(),//支付时间
            'payment_method'    => 'alipay',//支付方式
            'payment_no'        => $data->trade_no, //支付宝订单号
        ]);
       // \Log::debug('Alipay notify', $data->all());

        //触发支付成功后的事件
        $this->afterPaid($order);

        return app('alipay')->success();
    }

    //微信支付
    public function payByWechat(Order $order, Request $request)
    {
        //校验权限
        $this->authorize('own',$order);

        //校验订单状态
        if ($order->paid_at || $order->closed){
            throw new InternalException('订单状态不正确');
        }

        //scan 方法为拉起支付微信扫码支付
        $wechatOrder = app('wechat_pay')->scan([
            'out_trade_no'          => $order->no, //商户订单流水号，与支付宝 out_trade_no 一样
            'total_fee'             => $order->total_amount * 100,// 单位分
            'body'                  => '支付 laravel shop 订单:'.$order->no, //订单标题,
        ]);

        //把要转换的字符串作为 QrCode 的构造函数参数
        $qrCode = new QrCode($wechatOrder->code_url);

        //将生成的二维码图片数据以字符串形式输出,并带上相应的响应类型
        return response($qrCode->writeString(), 200, ['Content-Type' => $qrCode->getContentType() ]);
    }

    //微信服务端回调
    public function wechatNotify()
    {
        //校验回调参数是否正确
        $data = app('wechat_pay')->verify();

        //找到对应的订单
        $order = Order::where('no', $data->out_trade_no)->first();

        //订单不存在
        if (!$order){
            return 'fail';
        }

        //已支付
        if ($order->paid_at){
            //告知微信支付此订单已处理
            return app('wechat_pay')->success();
        }

        //将订单标记为已支付
        $order->update([
            'paid_at'           => Carbon::now(),//支付时间
            'payment_method'    => 'wechat',//支付方式
            'payment_no'        => $data->transaction_id, //支付宝订单号
        ]);

        //触发支付成功后的事件
        $this->afterPaid($order);

        return app('wechat_pay')->success();
    }

    //支付成功后触发事件
    protected function afterPaid(Order $order)
    {
        event(new OrderPaid($order));
    }

    //微信退款回调
    public function wechatRefundNotify(Request $request)
    {
        // 给微信的失败响应
        $failXml = '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>';
        $data = app('wechat_pay')->verify(null, true);

        //没有找到对应订单
        if (!$order = Order::where('no',$data['out_trade_no'])->first()){
            return $failXml;
        }

        if ($data['refund_status'] === 'SUCCESS'){
            //退款成功,将订单退款改成退款成功
            $order->update([
                'refund_status' => Order::REFUND_STATUS_SUCCESS,
            ]);
        }else{
            //退款失败
            $extra = $order->extra;
            $extra['refund_failed_code'] = $data['refund_status'];
            $order->update([
                'refund_staus'  => Order::REFUND_STATUS_FAILED
            ]);
        }

        return app('wechat_pay')->success();
    }
}
